import jwt from 'jsonwebtoken';
import { config } from '@/config';
import { logger } from './logger';

export interface JwtPayload {
  userId: string;
  type?: 'access' | 'refresh';
}

export interface TokenPair {
  accessToken: string;
  refreshToken: string;
}

// 生成访问令牌
export const generateAccessToken = (payload: Omit<JwtPayload, 'type'>): string => {
  try {
    return jwt.sign(
      { ...payload, type: 'access' },
      config.jwt.secret,
      { expiresIn: config.jwt.accessExpiresIn } as jwt.SignOptions
    );
  } catch (error) {
    logger.error('Failed to generate access token:', error);
    throw new Error('Token generation failed');
  }
};

// 生成刷新令牌
export const generateRefreshToken = (payload: Omit<JwtPayload, 'type'>): string => {
  try {
    return jwt.sign(
      { ...payload, type: 'refresh' },
      config.jwt.secret,
      { expiresIn: config.jwt.refreshExpiresIn } as jwt.SignOptions
    );
  } catch (error) {
    logger.error('Failed to generate refresh token:', error);
    throw new Error('Token generation failed');
  }
};

// 生成令牌对
export const generateTokenPair = (payload: Omit<JwtPayload, 'type'>): TokenPair => {
  return {
    accessToken: generateAccessToken(payload),
    refreshToken: generateRefreshToken(payload),
  };
};

// 验证令牌
export const verifyToken = (token: string): JwtPayload => {
  try {
    const decoded = jwt.verify(token, config.jwt.secret) as JwtPayload;
    return decoded;
  } catch (error) {
    if (error instanceof jwt.TokenExpiredError) {
      throw new Error('Token expired');
    } else if (error instanceof jwt.JsonWebTokenError) {
      throw new Error('Invalid token');
    } else {
      logger.error('Token verification failed:', error);
      throw new Error('Token verification failed');
    }
  }
};

// 解码令牌（不验证）
export const decodeToken = (token: string): JwtPayload | null => {
  try {
    const decoded = jwt.decode(token) as JwtPayload;
    return decoded;
  } catch (error) {
    logger.error('Token decode failed:', error);
    return null;
  }
};

// 检查令牌是否即将过期（剩余时间少于5分钟）
export const isTokenExpiringSoon = (token: string): boolean => {
  try {
    const decoded = jwt.decode(token) as any;
    if (!decoded || !decoded.exp) {
      return true;
    }
    
    const currentTime = Math.floor(Date.now() / 1000);
    const timeUntilExpiry = decoded.exp - currentTime;
    
    // 如果剩余时间少于5分钟（300秒），认为即将过期
    return timeUntilExpiry < 300;
  } catch (error) {
    logger.error('Failed to check token expiry:', error);
    return true;
  }
};